/**
 * 主线程:创建子线程
 * @param mix string|json 线程文件路径或选项
 * 		- string: 线程文件路径 等同{file:mix}
 * 		file: string 线程文件路径
 * 		...: mixed 线程选项  详见:原生文档
 * 			new Worker()的参数options
 * @param back function 消息回调 back(k,v,re)
 * 		- re: string|null 需要反馈时, 反馈KEY
 * 			if(re)必须: this.send(re, 反馈值)
 * 		k=_err: 异常时, v=异常, 原始异常数据
 * 		k=_exit: 子线程退出时, v=code<int>
 * 		k=_data: 非约定{k,v}格式消息, v=原值
 * 		k=$开头: 子线程内部转发  预留:待处理
 * 		k=string: 自定KEY, v:mixed,自定消息
 * @return this
 */
$.workerCreate = function(mix, back){
	if(!(this instanceof $.workerCreate))
		return new $.workerCreate(mix, back);
	if(typeof mix==='string') mix = {file:mix};
	const $W = require('node:worker_threads');
	let $w=new $W.Worker(mix.file,mix), v={value:{_:0}};
	Object.defineProperty(this, '__workerCreate', v);
	Object.defineProperty(this, '$worker', {value:$w});
	const M=this.__workerCreate;  back=back.bind(this);
	$w.on('error', err=>back('_err',err));
	$w.on('exit', code=>back('_exit',code));
	$w.on('message', v=>{
		let k=(v&&typeof v==='object'&&v.k)||'', p;
		if(k) v=v.v; else k='_data'; p=k.slice(0,9);
		if(p==='$worker.M'){ //收到:反馈消息<-子线程
			M[k].call(null,v); delete M[k];  return;
		}
		if(p!=='$worker.S') return back(k, v, null);
		back(k.split('#').slice(1).join('#'), v, k);
	});
	return this;
};
$.workerCreate.prototype = {
	constructor: $.workerCreate,
	/**
	 * 向子线程发消息
	 * @param k string 消息KEY  勿:_及$开头
	 * @param v mixed 消息内容  可序列化值
	 * @param re boolean 是否需反馈 false:否
	 *      反馈详见: $.worker()的back.re
	 * @return Promise|this  this:re=false时
	 *      Promise: re=true时,值为:反馈数据
	 */
	send(k, v, re=false){
		const $w=this.$worker, P='$.worker.M';
		if(!re){ $w.postMessage({k,v}); return this; }
		const T=this.__workerCreate, M=9999999999;
		return new Promise(resolve => {
			const K=P+(++T._)+'#'+k;  T[K]=resolve;
			if(T._>M) T._=0;  $w.postMessage({k:K,v});
		});
	},
	/**
	 * 停止子线程
	 * @return Promise<int>
	 */
	exit(){ return this.$worker.terminate(); },
};
